package com.ruoyi.project.rate.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.rate.Constants;
import com.ruoyi.project.rate.Utils;
import com.ruoyi.project.rate.domain.Cp;
import com.ruoyi.project.rate.domain.CpDetail;
import com.ruoyi.project.rate.service.CpDetailService;
import com.ruoyi.project.rate.service.CpService;
import com.ruoyi.project.system.config.service.IConfigService;
import com.ruoyi.project.system.dept.domain.Dept;
import com.ruoyi.project.system.dict.domain.DictData;
import com.ruoyi.project.system.dict.service.IDictDataService;
import com.ruoyi.project.system.role.domain.Role;
import com.ruoyi.project.system.role.service.IRoleService;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.service.IUserService;

@Controller
@RequestMapping("/rate/cp")
public class CpController extends BaseController {
	@Autowired
	private CpService cpService;
	@Autowired
	private CpDetailService cpDetailService;
	@Autowired
	private IConfigService configService;
	@Autowired
	private IRoleService roleService;
	@Autowired
	private IUserService userService;
	@Autowired
	private IDictDataService dictDataService;
	
	private String numOf100_ks_limit_default = "10";
	private String numOf100_jq_limit_default = "4";
	private String numOf60_ks_limit_default = "6";
	private String numOf60_jq_limit_default = "3";

	@RequestMapping("/cp")
	public String cp(Cp cp, ModelMap mmap) {
		String pageFlag = cp.getPageFlag();
		String type = cp.getType();
		if (StringUtils.isBlank(pageFlag)) {
			throw new RuntimeException("请求参数错误, pageFlag is blank.");
		}
		if (Constants.PAGE_FLAG_SUBMIT.equals(pageFlag) && StringUtils.isBlank(type)) {
			throw new RuntimeException("请求参数错误, type is blank.");
		}

		cp.setMonthId(Utils.lastMonth());
		mmap.put("cp", cp);

		return "rate/cpList";
	}

	@PostMapping("/list")
	@ResponseBody
	public TableDataInfo list(Cp cp) {
		String pageFlag = cp.getPageFlag();
		String type = cp.getType();
		if (StringUtils.isBlank(pageFlag)) {
			throw new RuntimeException("请求参数错误, pageFlag is blank.");
		}
		if (StringUtils.isBlank(cp.getMonthId())) {
			throw new RuntimeException("请选择考评月份！");
		}
		if (Constants.PAGE_FLAG_SUBMIT.equals(pageFlag)) {
			if (StringUtils.isBlank(type)) {
				throw new RuntimeException("请求参数错误, type is blank.");
			}
			
			if (Constants.CP_TYPE_LD.equals(type) || Constants.CP_TYPE_CJ.equals(type)) {
				cp.setCreateUser(ShiroUtils.getSysUser());
			} else if (Constants.CP_TYPE_JQ.equals(type) || Constants.CP_TYPE_KS.equals(type)) {
				cp.setDept(ShiroUtils.getSysDept());
			}
		}

		startPage();
		List<Cp> list = this.cpService.findList(cp);

		return getDataTable(list);
	}
	
	@RequestMapping("/cpNotSubmit")
	public String cpNotSubmit(Cp cp, ModelMap mmap) {
		cp.setMonthId(Utils.lastMonth());
		mmap.put("cp", cp);

		return "rate/cpNotSubmitList";
	}

	/**
	 * 查询没有提交测评的人员
	 * @param cp
	 * @return
	 */
	@PostMapping("/cpNotSubmitList")
	@ResponseBody
	public TableDataInfo cpNotSubmitList(Cp cp) {
		if (StringUtils.isBlank(cp.getMonthId())) {
			throw new RuntimeException("请选择考评月份！");
		}
		
		String type = cp.getType();
		List<String> roleKeys = new ArrayList<String>();
		if (StringUtils.isNotBlank(type)) {
			if (Constants.CP_TYPE_LD.equals(type)) {
				roleKeys = Arrays.asList("cp_ld");
			} else if (Constants.CP_TYPE_CJ.equals(type)) {
				roleKeys = Arrays.asList("cp_cj");
			} else if (Constants.CP_TYPE_JQ.equals(type)) {
				roleKeys = Arrays.asList("cp_jq");
			} else if (Constants.CP_TYPE_KS.equals(type)) {
				roleKeys = Arrays.asList("cp_ks");
			}
		}
		if (roleKeys.isEmpty()) {
			roleKeys = Arrays.asList("cp_ld", "cp_cj", "cp_jq", "cp_ks");
		}
		
		// 查询所有的role
		List<Role> roleList = new ArrayList<Role>();
		for (String roleKey : roleKeys) {
			Role role = new Role();
			role.setRoleKey(roleKey);
			List<Role> roles = this.roleService.selectRoleList(role);
			if (roles != null && roles.size() > 0) {
				roleList.add(roles.get(0));
			}
		}
		
		// 查询所有的user
		List<User> userList = new ArrayList<User>();
		for (Role role : roleList) {
			userList.addAll(this.userService.selectUserListByRoleId(role.getRoleId()));
		}
		
		// 查询所有的测评记录
		List<Cp> list = this.cpService.findList(cp);
		Map<String, Cp> cpMap = new HashMap<String, Cp>();
		for (Cp c : list) {
			cpMap.put(c.getCreateUser().getUserId().toString(), c);
		}
		
		Iterator<User> it = userList.iterator();
		while (it.hasNext()) {
			User u = it.next();
			if (cpMap.containsKey(u.getUserId().toString())) {
				it.remove();
			}
		}
		
		list = new ArrayList<Cp>();
		for (User u : userList) {
			Cp c = new Cp();
			c.setCreateUser(u);
			list.add(c);
		}
		
		return getDataTable(list);
	}

	@RequestMapping("/add")
	public String add(Cp cp, ModelMap mmap) {
		if (StringUtils.isBlank(cp.getType())) {
			throw new RuntimeException("type is blank.");
		}

		cp.setDept(ShiroUtils.getSysDept());
		cp.setPageFlag(Constants.PAGE_FLAG_ADD);
		
		cp.setMonthId(Utils.lastMonth());
		
		List<CpDetail> cpDetails = this.buildCpDetailListForEdit(cp);
		mmap.put("cp", cp);
		mmap.put("cpDetailList", cpDetails);
		mmap.put("tipsOfJq", this.buildTipsOfJq());
		mmap.put("tipsOfKs", this.buildTipsOfKs());
		
		Map<String, List<CpDetail>> split = this.splitToJqAndKs(cpDetails);
		mmap.put("cpDetailListOfJq", split.get("jq"));
		mmap.put("cpDetailListOfKs", split.get("ks"));

		return "rate/cpForm";
	}

	@RequestMapping("/edit")
	public String edit(Cp cp, ModelMap mmap) {
		Cp c = this.cpService.get(cp);
		if (c == null) {
			throw new RuntimeException("找不到对应的数据！");
		}
		c.setPageFlag(cp.getPageFlag());

		List<CpDetail> cpDetails = this.buildCpDetailListForEdit(c);
		mmap.put("cp", c);
		mmap.put("cpDetailList", cpDetails);
		mmap.put("tipsOfJq", this.buildTipsOfJq());
		mmap.put("tipsOfKs", this.buildTipsOfKs());
		
		Map<String, List<CpDetail>> split = this.splitToJqAndKs(cpDetails);
		mmap.put("cpDetailListOfJq", split.get("jq"));
		mmap.put("cpDetailListOfKs", split.get("ks"));

		return "rate/cpForm";
	}

	@PostMapping("/save")
	@ResponseBody
	public AjaxResult save(Cp cp, @RequestParam Map<String, String> requestMap) {
		String pageFlag = cp.getPageFlag();
		String type = cp.getType();
		if (StringUtils.isBlank(type)) {
			throw new RuntimeException("type is blank.");
		}
		if (StringUtils.isBlank(cp.getMonthId())) {
			throw new RuntimeException("month is blank.");
		}
		if (!StringUtils.equalsAny(pageFlag, "ADD", "EDIT")) {
			throw new RuntimeException("error pageFlag.");
		}
		
		// check duplicated
		Cp exist = new Cp();
		exist.setType(cp.getType());
		exist.setMonthId(cp.getMonthId());
		if (Constants.CP_TYPE_LD.equals(type)) {
			exist.setCreateUser(ShiroUtils.getSysUser());
		} else if (Constants.CP_TYPE_CJ.equals(type)) {
			exist.setCreateUser(ShiroUtils.getSysUser());
		} else if (Constants.CP_TYPE_JQ.equals(type) || Constants.CP_TYPE_KS.equals(type)) {
			exist.setDept(ShiroUtils.getSysDept());
		}
		List<Cp> exists = this.cpService.findList(exist);

		if (StringUtils.equals("ADD", pageFlag)) {
			// new report
			if (StringUtils.isNotBlank(cp.getId())) {
				throw new RuntimeException("request param error, id is not blank.");
			}
			if (exists.size() > 0) {
				throw new RuntimeException("当月已提交数据，无需重复提交！");
			}
			cp.setDept(ShiroUtils.getSysDept());
		} else if (StringUtils.equals("EDIT", pageFlag)) {
			Cp _c = this.cpService.get(cp);
			if (_c == null) {
				throw new RuntimeException("get report from db error！");
			}

			for (Cp e : exists) {
				if (e.getMonthId().equals(cp.getMonthId())
						&& !e.getId().equals(cp.getId())) {
					throw new RuntimeException("已存在月份【" + cp.getMonthId() + "】提交的数据！");
				}
			}
		}

		List<CpDetail> cpDetailList = this.buildCpDetailListByRequest(requestMap);
		
		// 校验测评结果个数
		int numOf100_ks_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof100_ks_limit"), numOf100_ks_limit_default));
		int numOf100_jq_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof100_jq_limit"), numOf100_jq_limit_default));
		int numOf60_ks_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof60_ks_limit"), numOf60_ks_limit_default));
		int numOf60_jq_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof60_jq_limit"), numOf60_jq_limit_default));
		int numOf100_ks = 0;
		int numOf100_jq = 0;
		int numOf60_ks = 0;
		int numOf60_jq = 0;
		Map<String, String> scoreMap = this.scoreAndLabelMap();
		for (CpDetail detail : cpDetailList) {
			boolean isJq = Utils.isJq(detail.getDept());
			if (detail.getScore() == null) {
				return AjaxResult.error("null score...");
			}
			
			String label = scoreMap.get(detail.getScore().toString());
			if (StringUtils.isNotBlank(label) && label.contains("优")) {
				if (isJq) {
					numOf100_jq++;
				} else {
					numOf100_ks++;
				}
			} else if (StringUtils.isNotBlank(label) && label.contains("一般")) {
				if (isJq) {
					numOf60_jq++;
				} else {
					numOf60_ks++;
				}
			} else {
				continue;
			}
		}
		StringBuilder sb = new StringBuilder();
		if (numOf100_jq > numOf100_jq_limit) {
			sb.append("评分为【优】的监区不得超过" + numOf100_jq_limit + "个；");
		}
		if (numOf100_ks > numOf100_ks_limit) {
			sb.append("评分为【优】的科室不得超过" + numOf100_ks_limit + "个；");
		}
		if (numOf60_jq < numOf60_jq_limit) {
			sb.append("评分为【一般】的监区不得少于" + numOf60_jq_limit + "个；");
		}
		if (numOf60_ks < numOf60_ks_limit) {
			sb.append("评分为【一般】的科室不得少于" + numOf60_ks_limit + "个；");
		}
		if (sb.length() > 0) {
			return AjaxResult.error(sb.toString());
		}
		
		cp.setStatus(Constants.CP_STATUS_DRAFT);
		this.cpService.save(cp, cpDetailList);

		return AjaxResult.success("保存成功！");
	}

	@RequestMapping("/submit")
	@ResponseBody
	public AjaxResult submit(Cp cp) {
		if (StringUtils.isBlank(cp.getId())) {
			throw new RuntimeException("请求参数cpId错误！");
		}

		cp = this.cpService.get(cp);
		if (cp == null) {
			throw new RuntimeException("can not find cp！");
		}
		
		cp.setStatus(Constants.CP_STATUS_APPROVED);
		this.cpService.updateStatus(cp);

		return AjaxResult.success("提交成功！");
	}
	
	@RequestMapping("/cancelSubmit")
	@ResponseBody
	public AjaxResult cancelSubmit(Cp cp) {
		if (StringUtils.isBlank(cp.getId())) {
			throw new RuntimeException("请求参数cpId错误！");
		}

		cp = this.cpService.get(cp);
		if (cp == null) {
			throw new RuntimeException("can not find cp！");
		}
		
		cp.setStatus(Constants.CP_STATUS_DRAFT);
		this.cpService.updateStatus(cp);

		return AjaxResult.success("撤回成功！");
	}
	
	@RequestMapping("/delete/{id}")
    @ResponseBody
    public AjaxResult delete(@PathVariable("id") String id) {
    	if (StringUtils.isBlank(id)) {
    		throw new RuntimeException("请求参数错误：【id=" + id + "】");
    	}
    	
    	Cp cp = this.cpService.get(id);
		if (cp == null) {
			throw new RuntimeException("找不到对应的数据！");
		}
		
		this.cpService.delete(cp);
		
    	return AjaxResult.success("删除成功！");
    }
	
	private List<CpDetail> buildCpDetailListForEdit(Cp cp) {
		List<CpDetail> cpDetailList;
		BigDecimal defaultScore = this.defaultScore();
		if (StringUtils.isBlank(cp.getId())) {
			cpDetailList = new ArrayList<>();
			List<Dept> depts = Utils.level2DeptList();
			for (Dept d : depts) {
				/**
				if (Utils.notKhDept(d)) {
					continue; // 非考核部门
				}
				**/
				CpDetail detail = new CpDetail();
				detail.setDept(d);
				detail.setScore(defaultScore);
				cpDetailList.add(detail);
			}
		} else {
			CpDetail detail = new CpDetail();
			detail.setCp(cp);
			cpDetailList = this.cpDetailService.findList(detail);
		}

		int i = 1;
		for (CpDetail d : cpDetailList) {
			d.setOrdr(i);
			d.setRelaId(i + "");
			i++;
		}

		return cpDetailList;
	}
	
	private Map<String, List<CpDetail>> splitToJqAndKs(List<CpDetail> details) {
		List<CpDetail> jqList = new ArrayList<>();
		List<CpDetail> ksList = new ArrayList<>();
		
		for (CpDetail d : details) {
			if (Utils.isJq(d.getDept())) {
				jqList.add(d);
			} else {
				ksList.add(d);
			}
		}
		
		Map<String, List<CpDetail>> result = new HashMap<>();
		result.put("jq", jqList);
		result.put("ks", ksList);
		return result;
	}

	private List<CpDetail> buildCpDetailListByRequest(Map<String, String> requestMap) {
		List<CpDetail> detailList = new ArrayList<>();
		Map<String,Dept> deptMap = Utils.mapDeptByDeptId();
		
		for (Map.Entry<String, String> entry : requestMap.entrySet()) {
			String key = entry.getKey();
			if (key.startsWith("cp_detail_id_")) {
				String relaId = key.substring(key.lastIndexOf("_") + 1);

				CpDetail cpDetail = new CpDetail();
				cpDetail.setId(requestMap.get("cp_detail_id_" + relaId));
				cpDetail.setOrdr(Integer.parseInt(requestMap.get("cp_detail_ordr_" + relaId)));
				cpDetail.setScore(new BigDecimal(requestMap.get("cp_detail_score_" + relaId)));
				
				String deptId = requestMap.get("cp_detail_deptId_" + relaId);
				Dept dept = deptMap.get(deptId);
				if (dept == null) {
					throw new RuntimeException("找不到部门：" + deptId);
				}
				cpDetail.setDept(dept);
				
				cpDetail.setRemark(requestMap.get("cp_detail_remark_" + relaId));

				detailList.add(cpDetail);
			}
		}
		return detailList;
	}
	
	private Map<String, String> scoreAndLabelMap() {
		DictData dd = new DictData();
		dd.setDictType(Constants.CP_SCORE);
		List<DictData> list = this.dictDataService.selectDictDataList(dd);
		Map<String, String> r = new HashMap<>();
		for (DictData d : list) {
			if (StringUtils.isNotBlank(d.getDictValue())
					&& StringUtils.isNotBlank(d.getDictLabel())) {
				r.put(d.getDictValue(), d.getDictLabel());
			}
		}
		
		return r;
	}
	private BigDecimal defaultScore() {
		Map<String, String> map = this.scoreAndLabelMap();
		List<String> values = new ArrayList<>();
		for (Map.Entry<String, String> e : map.entrySet()) {
			if (e.getValue().contains("良")) {
				values.add(e.getKey());
			}
		}
		Collections.sort(values);
		if (values.isEmpty()) {
			return null;
		}
		return new BigDecimal(values.get(values.size() - 1));
	}
	
	private String buildTipsOfJq() {
		int numOf100_jq_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof100_jq_limit"), numOf100_jq_limit_default));
		int numOf60_jq_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof60_jq_limit"), numOf60_jq_limit_default));
		StringBuilder sb = new StringBuilder();
		sb.append("<font color='red'>评分为【优】的监区不得超过【" + numOf100_jq_limit + "】个，</font><br/>");
		sb.append("<font color='green'>评分为【一般】的监区不得少于【" + numOf60_jq_limit + "】个。</font>");
		return sb.toString();
	}
	private String buildTipsOfKs() {
		int numOf100_ks_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof100_ks_limit"), numOf100_ks_limit_default));
		int numOf60_ks_limit = Integer.valueOf(StringUtils.defaultIfBlank(
				this.configService.selectConfigByKey("rate_cp_numof60_ks_limit"), numOf60_ks_limit_default));
		StringBuilder sb = new StringBuilder();
		sb.append("<font color='red'>评分为【优】的科室不得超过【" + numOf100_ks_limit + "】个，</font><br/>");
		sb.append("<font color='green'>评分为【一般】的科室不得少于【" + numOf60_ks_limit + "】个。</font>");
		return sb.toString();
	}
}